import { MongodbClient } from "../lib/db.client.mongodb";
import { PgClient } from "../lib/db.client.pg";

import { Book, User, Voucher, ENUM_BOOK_TYPE as ENUM_BOOK_TYPE_NEW, ENUM_BOOK_DIRECTION as ENUM_BOOK_DIRECTION_NEW, TonOrder } from "qqlx-core";
import { toDivideSafe, BookSchema, getConditionMatchStr, getBookTypeTrans } from "qqlx-cdk";

import { User as OldUser } from "../../../qqlx.old/qqlx-core";
import { ENUM_BOOK_DIRECTION, ENUM_BOOK_TYPE, Book as OldBook, BookOfOrder as OldBookOfOrder } from "../../../qqlx.old/qqlx-core";

import { Order as OldOrder } from "../../../qqlx.old/qqlx-core";
import { doBashPrint } from "../lib/log";
import { BookDao } from "../dao/pond/";
import { getTradeId } from "../lib/crypto";

export async function doVoucherOrderInsert(
  mongo_master_id: OldUser["_id"],
  _id_to_user_map: Map<OldOrder["_id"], User>,
  _id_to_sale_order_map: Map<OldOrder["_id"], TonOrder>,
  _id_to_buy_order_map: Map<OldOrder["_id"], TonOrder>,
  _id_to_voucher_map: Map<OldBook["_id"], Voucher>,
) {
  const mongodbClient = new MongodbClient("mongodb://localhost:27017/qqlx");
  const pgClient = new PgClient("127.0.0.1", "5432", "production", "postgres", "postgres");

  console.group("\n开始迁移mongo财务记录与订单的互相结清数据");
  const stat = { before: 0, wanner: 0, now: 0 };

  try {
    await mongodbClient.start();

    const oldBookIds: string[] = [];
    for (const { content } of _id_to_voucher_map.values()) oldBookIds.push(content);

    const colBookOfOrders = mongodbClient.getCollection("bookoforders");
    const mongo_union_book_list = await colBookOfOrders.find<OldBookOfOrder>({ bookId: { $in: oldBookIds } }).toArray();
    console.log("旧数据（货款/发票/结清明细）", mongo_union_book_list.length);
    stat.wanner = mongo_union_book_list.length * 2;

    // ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░░▄▄▄▄▄▄░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░▄█▀▀▀▀▀█▄░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░▄█░░▄▄▄░░█▄░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░█░░█▀▀█░░█░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░█░░█▀▀█░░█░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░█░░█▄▄█░░█░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░▀▄▀▄▄▄▄▄▀▄▀░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░

    const pgClientIns = await pgClient.start();
    const bookDao = new BookDao(pgClientIns.getRepository<Book>(BookSchema));
    const master = _id_to_user_map.get(mongo_master_id) as User;
    const condis = [getConditionMatchStr("refOwnerUUid32", master.uuid32)];

    const pgCount = await bookDao.count(condis);
    stat.before = pgCount;

    const bookSchemaLs: Book[] = [];
    for (const { bookId, orderId, bookType, bookDirection, amount } of mongo_union_book_list) {
      const tonOrder = _id_to_sale_order_map.get(orderId) || _id_to_buy_order_map.get(orderId);
      if (!tonOrder) throw new Error(`找不到订单`);

      const voucher = _id_to_voucher_map.get(bookId) as Voucher;
      if (!voucher) throw new Error(`找不到订单`);

      const base: Book = new BookSchema();
      base.refOwnerUUid32 = master.uuid32;
      base.coupleId = getTradeId();
      base.amount = toDivideSafe(amount, 100, 2);

      // 收钱
      if (bookType === ENUM_BOOK_TYPE.YSZK && bookDirection === ENUM_BOOK_DIRECTION.DAI) {
        const Jie = structuredClone(base);
        Jie.type = ENUM_BOOK_TYPE_NEW.YING_SHOU_ZHANG_KUAN_CHECKING;
        Jie.direction = ENUM_BOOK_DIRECTION_NEW.JIE;
        Jie.tradeId = voucher.tradeId;
        Jie.tradeTime = voucher.tradeTime;
        Jie.tradeYear = voucher.tradeYear;
        Jie.tradeMonth = voucher.tradeMonth;
        Jie.tradeScope = voucher.tradeScope;
        Jie.refContactId = voucher.refContactId;
        Jie.refCreatorId = voucher.refCreatorId;
        Jie.remark = getBookTypeTrans(Jie.type)?.zh || "";

        const Dai = structuredClone(base);
        Dai.type = ENUM_BOOK_TYPE_NEW.YING_SHOU_ZHANG_KUAN_ORDER;
        Dai.direction = ENUM_BOOK_DIRECTION_NEW.DAI;
        Dai.tradeId = tonOrder.tradeId;
        Dai.tradeTime = tonOrder.tradeTime;
        Dai.tradeYear = tonOrder.tradeYear;
        Dai.tradeMonth = tonOrder.tradeMonth;
        Dai.tradeScope = tonOrder.tradeScope;
        Dai.refContactId = tonOrder.refContactId;
        Dai.refCreatorId = tonOrder.refCreatorId;
        Dai.remark = getBookTypeTrans(Dai.type)?.zh || "";
        bookSchemaLs.push(...[Jie, Dai]);
      }
      // 开发票
      else if (bookType === ENUM_BOOK_TYPE.YSZK_VAT && bookDirection === ENUM_BOOK_DIRECTION.JIE) {
        const Jie = structuredClone(base);
        Jie.type = ENUM_BOOK_TYPE_NEW.ZHU_YING_YE_WU_SHOU_RU_ORDER;
        Jie.direction = ENUM_BOOK_DIRECTION_NEW.JIE;
        Jie.tradeId = tonOrder.tradeId;
        Jie.tradeTime = tonOrder.tradeTime;
        Jie.tradeYear = tonOrder.tradeYear;
        Jie.tradeMonth = tonOrder.tradeMonth;
        Jie.tradeScope = tonOrder.tradeScope;
        Jie.refContactId = tonOrder.refContactId;
        Jie.refCreatorId = tonOrder.refCreatorId;
        Jie.remark = getBookTypeTrans(Jie.type)?.zh || "";

        const Dai = structuredClone(base);
        Dai.type = ENUM_BOOK_TYPE_NEW.ZHU_YING_YE_WU_SHOU_RU_CHECKING;
        Dai.direction = ENUM_BOOK_DIRECTION_NEW.DAI;
        Dai.tradeId = voucher.tradeId;
        Dai.tradeTime = voucher.tradeTime;
        Dai.tradeYear = voucher.tradeYear;
        Dai.tradeMonth = voucher.tradeMonth;
        Dai.tradeScope = voucher.tradeScope;
        Dai.refContactId = voucher.refContactId;
        Dai.refCreatorId = voucher.refCreatorId;
        Dai.remark = getBookTypeTrans(Dai.type)?.zh || "";
        bookSchemaLs.push(...[Jie, Dai]);
      }
      // 付款
      else if (bookType === ENUM_BOOK_TYPE.YFZK && bookDirection === ENUM_BOOK_DIRECTION.JIE) {
        const Jie = structuredClone(base);
        Jie.type = ENUM_BOOK_TYPE_NEW.YING_FU_ZHANG_KUAN_ORDER;
        Jie.direction = ENUM_BOOK_DIRECTION_NEW.JIE;
        Jie.tradeId = tonOrder.tradeId;
        Jie.tradeTime = tonOrder.tradeTime;
        Jie.tradeYear = tonOrder.tradeYear;
        Jie.tradeMonth = tonOrder.tradeMonth;
        Jie.tradeScope = tonOrder.tradeScope;
        Jie.refContactId = tonOrder.refContactId;
        Jie.refCreatorId = tonOrder.refCreatorId;
        Jie.remark = getBookTypeTrans(Jie.type)?.zh || "";

        const Dai = structuredClone(base);
        Dai.type = ENUM_BOOK_TYPE_NEW.YING_FU_ZHANG_KUAN_CHECKING;
        Dai.direction = ENUM_BOOK_DIRECTION_NEW.DAI;
        Dai.tradeId = voucher.tradeId;
        Dai.tradeTime = voucher.tradeTime;
        Dai.tradeYear = voucher.tradeYear;
        Dai.tradeMonth = voucher.tradeMonth;
        Dai.tradeScope = voucher.tradeScope;
        Dai.refContactId = voucher.refContactId;
        Dai.refCreatorId = voucher.refCreatorId;
        Dai.remark = getBookTypeTrans(Dai.type)?.zh || "";
        bookSchemaLs.push(...[Jie, Dai]);
      }
      // 收到发票
      else if (bookType === ENUM_BOOK_TYPE.YFZK_VAT && bookDirection === ENUM_BOOK_DIRECTION.DAI) {
        const Jie = structuredClone(base);
        Jie.type = ENUM_BOOK_TYPE_NEW.ZHU_YING_YE_WU_CHENG_BEN_CHECKING;
        Jie.direction = ENUM_BOOK_DIRECTION_NEW.JIE;
        Jie.tradeId = voucher.tradeId;
        Jie.tradeTime = voucher.tradeTime;
        Jie.tradeYear = voucher.tradeYear;
        Jie.tradeMonth = voucher.tradeMonth;
        Jie.tradeScope = voucher.tradeScope;
        Jie.refContactId = voucher.refContactId;
        Jie.refCreatorId = voucher.refCreatorId;
        Jie.remark = getBookTypeTrans(Jie.type)?.zh || "";

        const Dai = structuredClone(base);
        Dai.type = ENUM_BOOK_TYPE_NEW.ZHU_YING_YE_WU_CHENG_BEN_ORDER;
        Dai.direction = ENUM_BOOK_DIRECTION_NEW.DAI;
        Dai.tradeId = tonOrder.tradeId;
        Dai.tradeTime = tonOrder.tradeTime;
        Dai.tradeYear = tonOrder.tradeYear;
        Dai.tradeMonth = tonOrder.tradeMonth;
        Dai.tradeScope = tonOrder.tradeScope;
        Dai.refContactId = tonOrder.refContactId;
        Dai.refCreatorId = tonOrder.refCreatorId;
        Dai.remark = getBookTypeTrans(Dai.type)?.zh || "";
        bookSchemaLs.push(...[Jie, Dai]);
      }
      // 报错
      else {
        throw { message: `财务记录类型异常` };
      }
    }

    const batchCount = 2000;
    while (bookSchemaLs.length > 0) {
      const part = bookSchemaLs.splice(0, batchCount);
      await bookDao.insertManyAndQuery(part);
      doBashPrint(`正在对财务记录/订单进行联合记账（${batchCount}）剩余${bookSchemaLs.length}`);
    }

    const pgCountFinal = await bookDao.count(condis);
    stat.now = pgCountFinal;

    console.log(`🔴迁移前 >> 迁移后 / river_ton_order`, stat.before, stat.now);
    console.log(`期望`, stat.wanner);
    console.log(`📉误差`, stat.now - stat.before - stat.wanner);
    console.groupEnd();
    console.log("====================================");
  } finally {
    await pgClient.stop();
    await mongodbClient.stop();
  }
}
